Skip to contentMethod: setChildren(TreeItem, int)
1: /*
2: * *************************************************************************************************************************************************************
3: *
4: * SteelBlue: DCI User Interfaces
5: * http://tidalwave.it/projects/steelblue
6: *
7: * Copyright (C) 2015 - 2024 by Tidalwave s.a.s. (http://tidalwave.it)
8: *
9: * *************************************************************************************************************************************************************
10: *
11: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
12: * You may obtain a copy of the License at
13: *
14: * http://www.apache.org/licenses/LICENSE-2.0
15: *
16: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
17: * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
18: *
19: * *************************************************************************************************************************************************************
20: *
21: * git clone https://bitbucket.org/tidalwave/steelblue-src
22: * git clone https://github.com/tidalwave-it/steelblue-src
23: *
24: * *************************************************************************************************************************************************************
25: */
26: package it.tidalwave.role.ui.javafx.impl.common;
27:
28: import javax.annotation.Nonnull;
29: import java.beans.PropertyChangeListener;
30: import java.util.concurrent.Executor;
31: import javafx.beans.property.ObjectProperty;
32: import javafx.beans.property.ReadOnlyObjectProperty;
33: import javafx.scene.control.TreeItem;
34: import javafx.application.Platform;
35: import it.tidalwave.util.annotation.VisibleForTesting;
36: import it.tidalwave.role.ui.PresentationModel;
37: import it.tidalwave.role.ui.Visible;
38: import it.tidalwave.role.ui.javafx.impl.tree.ObsoletePresentationModelDisposer;
39: import lombok.Getter;
40: import lombok.extern.slf4j.Slf4j;
41: import static java.util.stream.Collectors.*;
42: import static it.tidalwave.role.ui.Visible._Visible_;
43: import static it.tidalwave.role.ui.javafx.impl.common.JavaFXWorker.childrenPm;
44:
45: /***************************************************************************************************************************************************************
46: *
47: * Some common stuff for both {@code TreeView} and {@code TreeTableView}.
48: *
49: * @author Fabrizio Giudici
50: *
51: **************************************************************************************************************************************************************/
52: @Slf4j
53: public class TreeItemDelegateSupport extends DelegateSupport
54: {
55: @VisibleForTesting @Getter()
56: private final ChangeListenerSelectableAdapter selectionListener = new ChangeListenerSelectableAdapter(executor);
57:
58: private final ObsoletePresentationModelDisposer presentationModelDisposer = new ObsoletePresentationModelDisposer();
59:
60: /***********************************************************************************************************************************************************
61: *
62: **********************************************************************************************************************************************************/
63: public TreeItemDelegateSupport (@Nonnull final Executor executor)
64: {
65: super(executor);
66: }
67:
68: /***********************************************************************************************************************************************************
69: * Sets the children for a {@link TreeItem}.
70: *
71: * @param parentItem the {@code TreeItem}
72: * @param depth the depth level (used only for logging)
73: **********************************************************************************************************************************************************/
74: protected void setChildren (@Nonnull final TreeItem<PresentationModel> parentItem, final int depth)
75: {
76: JavaFXWorker.run(executor,
77: () -> childrenPm(parentItem.getValue(), depth),
78: items -> parentItem.getChildren().setAll(items.stream()
79: .map(childPm -> createTreeItem(childPm, depth))
80: .collect(toList())));
81: }
82:
83: /***********************************************************************************************************************************************************
84: * Creates a single {@link TreeItem} for the given the {@link PresentationModel}. When the {@code PresentationModel}
85: * fires the {@link PresentationModel#PROPERTY_CHILDREN} property change event, children are recreated.
86: *
87: * @param pm the {@code PresentationModel}
88: * @param depth the depth level (used only for logging)
89: * @return the
90: **********************************************************************************************************************************************************/
91: @Nonnull
92: protected TreeItem<PresentationModel> createTreeItem (@Nonnull final PresentationModel pm, final int depth)
93: {
94: assertIsFxApplicationThread();
95: final TreeItem<PresentationModel> item = new PresentationModelTreeItem(pm);
96:
97: final PropertyChangeListener recreateChildrenOnUpdateListener = __ ->
98: Platform.runLater(() ->
99: {
100: log.debug("On recreateChildrenOnUpdateListener");
101: setChildren(item, depth + 1);
102: item.setExpanded(true);
103: });
104:
105: pm.addPropertyChangeListener(PresentationModel.PROPERTY_CHILDREN, recreateChildrenOnUpdateListener);
106:
107: item.expandedProperty().addListener((observable, oldValue, newValue) ->
108: {
109: if (newValue)
110: {
111: setChildren(item, depth + 1);
112: }
113: });
114:
115: return item;
116: }
117:
118: /***********************************************************************************************************************************************************
119: *
120: **********************************************************************************************************************************************************/
121: protected void setRootProperty (@Nonnull final PresentationModel pm,
122: @Nonnull final ObjectProperty<TreeItem<PresentationModel>> rootProperty)
123: {
124: rootProperty.removeListener(presentationModelDisposer);
125: rootProperty.addListener(presentationModelDisposer);
126: rootProperty.set(createTreeItem(pm, 0));
127: }
128:
129: /***********************************************************************************************************************************************************
130: *
131: **********************************************************************************************************************************************************/
132: protected void bindSelectionListener (@Nonnull final ReadOnlyObjectProperty<TreeItem<PresentationModel>> selectedItemProperty)
133: {
134: selectedItemProperty.removeListener(selectionListener.asTreeItemChangeListener());
135: selectedItemProperty.addListener(selectionListener.asTreeItemChangeListener());
136: }
137:
138: /***********************************************************************************************************************************************************
139: *
140: **********************************************************************************************************************************************************/
141: protected static Boolean shouldShowRoot (@Nonnull final PresentationModel pm)
142: {
143: return pm.maybeAs(_Visible_).map(Visible::isVisible).orElse(true);
144: }
145: }